package com.tristia.resources.impl;

import java.util.List;

import javax.annotation.Resource;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.sun.jersey.api.NotFoundException;
import com.tristia.dao.GenericDao;
import com.tristia.entity.Cd;
import com.tristia.entity.Cds;
import com.tristia.entity.Track;
import com.tristia.entity.Tracks;

@Component
@Path("/cds")
@Scope("request")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML })
public class CdsResWs {
	@Resource
	GenericDao<Cd, Long> cdDao;
	@Context 
	UriInfo ui;
	@Context
	Request request;
	private Logger log = Logger.getLogger(this.getClass());
	
	@GET
	public Cds getCds() {
		log.info("getCds entered");
		Cds cds = new Cds();
		cds.setCds(cdDao.getAll());
		log.info("Sending: \n\n" + cds.toString() + "\n\n");
		return cds;
	}
	
/*	@Path("/{cdId}")
	public CdResWs getCdResWs(@PathParam("cdId") String cdId) {
		log.info("getCd entered");
		return new CdResWs(cdDao, ui, request, cdId);
	}*/
	
	@GET
	@Path("/{cdId}")
	public Cd getCd(@PathParam("cdId") long cdId) {
		log.info("getCd entered");
		Cd cd = cdDao.get(cdId);
		if (cd == null)throw new NotFoundException("Cd not found");
		log.info("Sending: \n\n" + cd.toString() + "\n\n");
		return cd;
	}
	
	@PUT
	public Response updateCd(@QueryParam("id") String id,
			@QueryParam("title") String title,
			@QueryParam("author") String author) {
		log.info("updateCd entered");
		log.info("title: " + title);
		log.info("author : " + author);
		log.info("id : " + id);
		
		Response r;
//		URI uri =  ui.getAbsolutePath();
		if (StringUtils.hasText(id)) {
			log.info("It has an ID");
			long idd = Long.parseLong(id);
			boolean cdExists = cdDao.exists(idd);
			if (cdExists == true) {
				log.info("We found the cd with that id");
				Cd cd = cdDao.get(idd);
				cd.setTitle(title);
				cd.setAuthor(author);
				cdDao.save(cd);
				log.info("Updated successfully");
//				r = Response.created(uri).build();
				r = Response.ok(cd).build();
			} else {
				log.info("We do not found the cd with that id");
				r = Response.noContent().build();
			}
		} else {
			log.info("It doesn't have an ID");
			log.info("Put the new cd");
			Cd cd = new Cd();
			cd.setTitle(title);
			cd.setAuthor(author);
			cdDao.save(cd);
			log.info("Updated successfully");
			r = Response.ok(cd).build();
		}
		return r;
	}
	
	@POST
	@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_XML })
	public Response addCd(@QueryParam("title") String title,
			@QueryParam("author") String author) {
		log.info("addCd entered");
		log.info("title: " + title);
		log.info("author : " + author);

//		SuccessInfo successInfo = new SuccessInfo();
		Response r;
		Cd cd = new Cd();
		cd.setTitle(title);
		cd.setAuthor(author);
		cdDao.save(cd);
		log.info("Updated successfully");
		r = Response.ok(cd).build();
//		successInfo.getSuccesses().add("Created successfully");
		return r;
	}
	
	@DELETE
	@Path("/{cdId}")
	public void deleteCd(@PathParam("cdId") String cdId) {
		if(cdId!=null) {
			deleteCdById(cdId);
		}
		
		MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
		List<String> ids = queryParams.get("cdId");
		if(ids == null) {
			log.info("\n\nThe ids is null");
		} else {
			for (String currentid : ids) {
				deleteCdById(currentid);
			}
		}
	}

	private void deleteCdById(String id) {
		log.info("Delete Id: " + id);
		Cd cd = cdDao.get(Long.parseLong(id));
		if (cd == null) {
			log.info("Null was returned for ID: " + id);
		} else {
			cdDao.remove(Long.parseLong(id));
			log.info("Deleted the CD with ID:" + id);
		}
	}
	
	@GET
	@Path("/{cdId}/tracks")
	public Tracks getTracks(@PathParam("cdId") long cdId) {
		log.info("getTracks entered");
		Tracks tracks = new Tracks();
		log.info("Tracks num: " + cdDao.get(cdId).getTracks().size());
		tracks.setTracks(cdDao.get(cdId).getTracks());
		log.info("Sending: \n\n" + tracks.toString() + "\n\n");
		return tracks;
	}
	
	@Path("/{cdId}/tracks/{trackId}")
	public Track getTrack(@PathParam("cdId") long cdId, @PathParam("trackId") int trackId) {
		log.info("getTrack entered");
		List<Track> tracks = cdDao.get(cdId).getTracks();
		if (trackId > tracks.size())
            throw new NotFoundException("Track, " + trackId + ", of CD, " + cdDao.get(cdId).getTitle() + ", is not found");
		Track track = tracks.get(trackId-1);
		if (track == null)throw new NotFoundException("Track not found");
		log.info("Sending: \n\n" + track.toString() + "\n\n");
		return track;
	}

}
